package stage1.module2.Q2;

public class Board {

    public final static String HEADER = "0123456789abcdefghigjlmnopqrstuvwxyz";
    public final static String PLACEHOLDER = " ";

    private char[][] board;
    private int size;

    public Board(int size) {
        this.size = size;
        board = initBoard(size);
    }

    /**
     * 初始化棋盘
     * @param size 棋盘的大小
     * @return 一个棋盘，以2D的char数组的形式表示出来，+代表空位置，b代表黑方棋子，w代表白方棋子
     */
    private char[][] initBoard(int size) {
        char[][] board = new char[size][size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                board[i][j] = '+';
            }
        }
        return board;
    }

    /**
     * 打印棋盘
     */
    public void printBoard() {
        System.out.println("Start printing board...");
        System.out.print(PLACEHOLDER + PLACEHOLDER);
        for (int i = 0; i < size; i++) {
            System.out.print(HEADER.charAt(i) + PLACEHOLDER);
        }
        System.out.println();

        for (int i = 0; i < size; i++) {
            System.out.print(HEADER.charAt(i) + PLACEHOLDER);
            for (int j = 0; j < size; j++) {
                System.out.print(board[i][j]);
                System.out.print(PLACEHOLDER);
            }
            System.out.println();
        }
        System.out.println();
    }

    /**
     * 在棋盘上落一个子
     * @param piece 准备被落到棋盘上的子
     * @param row 棋子准备被放到的位置的行数
     * @param col 棋子准备被放到的位置的列数
     * @return 一个整数，代表操作的状态，0代表成功，-1代表无效的位置，1代表已占用的位置
     */
    public int putPiece(char piece, String row, String col) {
        int rowIndex = HEADER.indexOf(row);
        int colIndex = HEADER.indexOf(col);
        if (rowIndex >= size || colIndex >= size) {
            return -1;
        }
        if (board[rowIndex][colIndex] != '+') {
            return 1;
        }
        board[rowIndex][colIndex] = piece;
        return 0;
    }

    /**
     * 检查输入棋子的玩家是否是赢家
     * @param piece 准备被检查的棋子
     * @param row 棋子的行数
     * @param col 棋子的列数
     * @return true如果输入棋子的玩家是赢家，否则false
     */
    public boolean checkWinner(char piece, String row, String col) {
        int rowIndex = HEADER.indexOf(row);
        int colIndex = HEADER.indexOf(col);

        if (getRowCount(piece, rowIndex, colIndex) >= 5) {
            return true;
        }
        if (getColCount(piece, rowIndex, colIndex) >= 5) {
            return true;
        }
        if (getDiagonalCount(piece, rowIndex, colIndex) >= 5) {
            return true;
        }
        if (getInverseDiagonalCount(piece, rowIndex, colIndex) >= 5) {
            return true;
        }
        return false;
    }

    // 对于给定的棋子与行列数，计算同一列相邻的相同棋子个数
    private int getColCount(char piece,int row, int col) {
        int count = 1;
        int temp;

        // 持续往上计数直到遇到不同的棋子(或者空位置)
        for (int i = 1; i < size; i++) {
            temp = row - i;
            // 碰到边界
            if (temp < 0) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[temp][col] != piece) {
                break;
            }
            count++;
        }

        // 持续往下计数直到遇到不同的棋子(或者空位置)
        for (int i = 1; i < size; i++) {
            temp = row + i;
            // 碰到边界
            if (temp >= size) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[row + i][col] != piece) {
                break;
            }
            count++;
        }
        return count;
    }

    // 对于给定的棋子与行列数，计算同一行相邻的相同棋子个数
    private int getRowCount(char piece, int row, int col) {
        int count = 1;
        int temp;

        // 持续往左计数直到遇到不同的棋子(或者空位置)
        for (int i = 1; i < size; i++) {
            temp = col - i;
            // 碰到边界
            if (temp < 0) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[row][temp] != piece) {
                break;
            }
            count++;
        }

        // 持续往右计数直到遇到不同的棋子(或者空位置)
        for (int i = 1; i < size; i++) {
            temp = col + i;
            // 碰到边界
            if (temp >= size) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[row][temp] != piece) {
                break;
            }
            count++;
        }
        return count;
    }

    // 对于给定的棋子与行列数，计算同一对角线(左上-右下)相邻的相同棋子个数
    private int getDiagonalCount(char piece, int row, int col) {
        int count = 1;
        int tempRow, tempCol;

        // 持续计数直到遇到边界或者不同的棋子(或者空位置)
        // 左上方向
        for (int i = 1; i <= size; i++) {
            tempRow = row - i;
            tempCol = col - i;
            // 碰到边界
            if (tempRow < 0 || tempCol < 0) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[tempRow][tempCol] != piece) {
                break;
            }
            count++;
        }
        
        // 右下方向
        for (int i = 1; i <= size; i++) {
            tempRow = row + i;
            tempCol = col + i;
            // 碰到边界
            if (tempRow >= size || tempCol >= size) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[tempRow][tempCol] != piece) {
                break;
            }
            count++;
        }
        
        return count;
    }

    // 对于给定的棋子与行列数，计算同一对角线(左下-右上)相邻的相同棋子个数
    private int getInverseDiagonalCount(char piece, int row, int col) {
        int count = 1;
        int tempRow, tempCol;

        // 持续计数直到遇到边界或者不同的棋子(或者空位置)
        // 右上方向
        for (int i = 1; i <= size; i++) {
            tempRow = row - i;
            tempCol = col + i;
            // 碰到边界
            if (tempRow < 0 || tempCol >= size) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[tempRow][tempCol] != piece) {
                break;
            }
            count++;
        }

        // 左下方向
        for (int i = 1; i <= size; i++) {
            tempRow = row + i;
            tempCol = col - i;
            // 碰到边界
            if (tempRow >= size || tempCol < 0) {
                break;
            }
            // 碰到不用的棋子(或者空位置)
            if (board[tempRow][tempCol] != piece) {
                break;
            }
            count++;
        }

        return count;
    }
 }
